package com.fastloan.mgt.model.service.arithmetic.selfsupport;

import com.fastloan.common.functioninterface.Try;
import com.fastloan.mgt.model.model.CreditModel;
import com.fastloan.mgt.model.service.arithmetic.selfsupport.weight.SelfSupportCreditModelWeight;
import com.fastloan.mgt.model.service.arithmetic.selfsupport.weight.SelfSupportCreditModelWeightImpl;
import com.fastloan.utils.DateTimeUtil;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

public class SelfSupportCreditModel extends CreditModel {

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 婚姻状况
     */
    private String maritalStatus;

    /**
     * 经济依附人数
     */
    private Integer economicDependencyNum;

    /**
     * 是否本地
     */
    private String local;

    /**
     * 居住年限
     */
    private Integer liveTime;

    /**
     * 学历
     */
    private String education;

    /**
     * 业务开始日期
     */
    private String manageTime;

    /**
     * 贷款逾期累计月数
     */
    private Integer loanOverdueMonthCount;

    /**
     * 信用卡逾期累计月数
     */
    private Integer creditCardMonthCount;

    /**
     * 是否正常纳税
     */
    private String taxStatus;

    /**
     * 银行存款
     */
    private BigDecimal bankMoney = BigDecimal.ZERO;

    /**
     * 股票
     */
    private BigDecimal stockMoney = BigDecimal.ZERO;

    /**
     * 理财产品
     */
    private BigDecimal manageProductMoney = BigDecimal.ZERO;

    /**
     * 证券价值
     */
    private BigDecimal securityMoney = BigDecimal.ZERO;

    /**
     * 基金价值
     */
    private BigDecimal fundMoney = BigDecimal.ZERO;

    /**
     * 房产现值
     */
    private BigDecimal houseMoney = BigDecimal.ZERO;

    /**
     * 车产现值
     */
    private BigDecimal carMoney = BigDecimal.ZERO;

    /**
     * 房产按揭贷款余额
     */
    private BigDecimal houseMortgageBalance = BigDecimal.ZERO;

    /**
     * 车贷余额
     */
    private BigDecimal carMortgageBalance = BigDecimal.ZERO;

    /**
     * 贷款余额
     */
    private BigDecimal loanBalance = BigDecimal.ZERO;

    /**
     * 月可支
     */
    private BigDecimal monthControlMoney = BigDecimal.ZERO;

    /**
     * 贷款月数
     */
    private Integer loanMonth = 0;

    private SelfSupportCreditModelWeight selfSupportCreditModelWeight;

    public SelfSupportCreditModel(SelfSupportCreditModelWeight selfSupportCreditModelWeight) {
        this.selfSupportCreditModelWeight = selfSupportCreditModelWeight;
    }

    public Integer getAge() {
        return age;
    }

    public double getAgeScore(){
        Integer age = getAge();
        double weight = selfSupportCreditModelWeight.getAgeWeight();
        if (age == null){
            return weight * 1;
        }
        if (age > 40 && age <= 60){
            return weight * 0.80;
        } else if(age > 35 && age <= 45){
            return weight * 0.95;
        } else if(age > 30 && age <= 35){
            return weight * 1;
        } else if(age > 25 && age <= 30){
            return weight * 0.95;
        } else if (age <= 25){
            return weight * 0.95;
        } else {
            return weight * 1;
        }
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getMaritalStatus() {
        return maritalStatus;
    }

    public double getMaritalStatusScore() {
        String maritalStatus = getMaritalStatus();
        double weight = selfSupportCreditModelWeight.getMaritalStatusWeight();
        if (maritalStatus == null){
            return weight * 1;
        }
        switch (maritalStatus){
            case "未婚":
                return weight * 0.80;
            case "已婚":
                return weight * 1;
            case "离异":
                return weight * 0.80;
            case "再婚":
                return weight * 0.50;
            case "丧偶":
                return weight * 0.80;
            default:
                return weight * 1;
        }
    }

    public void setMaritalStatus(String maritalStatus) {
        this.maritalStatus = maritalStatus;
    }

    public Integer getEconomicDependencyNum() {
        return economicDependencyNum;
    }

    public Double getEconomicDependencyNumScore() {
        Integer economicDependencyNum = getEconomicDependencyNum();
        Double weight = selfSupportCreditModelWeight.getEconomicDependencyNumWeight();
        if (economicDependencyNum == null){
            return weight * 1;
        }
        if (economicDependencyNum == 0){
            return weight * 0.80;
        } else {
            return weight * 1;
        }
    }

    public void setEconomicDependencyNum(Integer economicDependencyNum) {
        this.economicDependencyNum = economicDependencyNum;
    }

    public String getLocal() {
        return local;
    }

    public void setLocal(String local) {
        this.local = local;
    }

    public Integer getLiveTime() {
        return liveTime;
    }

    public void setLiveTime(Integer liveTime) {
        this.liveTime = liveTime;
    }

    public Double getLiveTimeAndIsLocalScore(){
        Double weight = selfSupportCreditModelWeight.getLiveTimeAndIsLocalWeight();
        Integer liveTime = getLiveTime();
        String local = getLocal();
        if ("是".equals(local) || liveTime == null){
            return weight * 1;
        }
        if (liveTime >= 3){
            return weight * 0.80;
        } else {
            return weight * 0.50;
        }
    }

    public String getEducation() {
        return education;
    }

    public Double getEducationScore() {
        String education = getEducation();
        Double weight = selfSupportCreditModelWeight.getEducationWeight();
        List<String> groupOne = Arrays.asList("文盲", "小学", "初中");
        List<String> groupTwo = Arrays.asList("中专", "高中");
        List<String> groupThree = Arrays.asList("大专");
        List<String> groupFour = Arrays.asList("本科");
        List<String> groupFive = Arrays.asList("硕士","博士","博士后");
        if (groupOne.contains(education)){
            return weight * 0.6;
        } else if(groupTwo.contains(education)){
            return weight * 0.7;
        } else if(groupThree.contains(education)){
            return weight * 0.8;
        } else if(groupFour.contains(education)){
            return weight * 0.9;
        } else if(groupFive.contains(education)){
            return weight * 1;
        } else {
            return weight * 0.8;
        }
    }

    public void setEducation(String education) {
        this.education = education;
    }

    public String getManageTime() {
        return manageTime;
    }

    public Double getManageTimeScore() {
        Double weight = selfSupportCreditModelWeight.getManageTimeWeight();
        String manageStartTime = getManageTime();
        if (manageStartTime == null || "".equals(manageStartTime)){
            return weight * 0.8;
        }
        Instant beginInstant = DateTimeUtil.format(manageStartTime,DateTimeUtil.NORM_DATE_PATTERN).toInstant();
        Instant endInstant = new Date().toInstant();
        Duration duration = Duration.between(beginInstant, endInstant);
        long seconds = duration.getSeconds();
        double manageTime = seconds / (365 * 24 * 60 * 60) * 1d;
        if (manageTime >= 5){
            return weight * 1;
        } else if(manageTime >= 2){
            return weight * 0.8;
        } else if(manageTime >= 1){
            return weight * 0.5;
        } else if (manageTime >= 0){
            return weight * 0;
        } else {
            return weight * 0.8;
        }
    }

    public void setManageTime(String manageTime) {
        this.manageTime = manageTime;
    }

    public Integer getLoanOverdueMonthCount() {
        return loanOverdueMonthCount;
    }

    public void setLoanOverdueMonthCount(Integer loanOverdueMonthCount) {
        this.loanOverdueMonthCount = loanOverdueMonthCount;
    }

    public Integer getCreditCardMonthCount() {
        return creditCardMonthCount;
    }

    public void setCreditCardMonthCount(Integer creditCardMonthCount) {
        this.creditCardMonthCount = creditCardMonthCount;
    }

    public Double getCreditCardAndLoanOverdueScore(){
        Double weight = selfSupportCreditModelWeight.getCreditCardAddLoanOverdueWeight();
        if (getCreditCardMonthCount() == null || getLoanOverdueMonthCount() == null){
            return weight * 1;
        }
        Integer count = getCreditCardMonthCount() + getLoanOverdueMonthCount();
        if (count >= 6){
            return weight * 1;
        } else if(count >= 4){
            return weight * 0.6;
        } else if(count >= 1){
            return weight * 0.9;
        } else if(count == 0){
            return weight * 1;
        } else {
            return weight * 1;
        }
    }

    public String getTaxStatus() {
        return taxStatus;
    }

    public Double getTaxStatusScore() {
        String taxStatus = getTaxStatus();
        Double weight = selfSupportCreditModelWeight.getPayTaxesWeight();
        if ("是".equals(taxStatus)){
            return weight * 1;
        } else {
            return weight * 0;
        }
    }

    public void setTaxStatus(String taxStatus) {
        this.taxStatus = taxStatus;
    }

    public BigDecimal getBankMoney() {
        return bankMoney;
    }

    public void setBankMoney(BigDecimal bankMoney) {
        this.bankMoney = bankMoney;
    }

    public BigDecimal getStockMoney() {
        return stockMoney;
    }

    public void setStockMoney(BigDecimal stockMoney) {
        this.stockMoney = stockMoney;
    }

    public BigDecimal getManageProductMoney() {
        return manageProductMoney;
    }

    public void setManageProductMoney(BigDecimal manageProductMoney) {
        this.manageProductMoney = manageProductMoney;
    }

    public BigDecimal getSecurityMoney() {
        return securityMoney;
    }

    public void setSecurityMoney(BigDecimal securityMoney) {
        this.securityMoney = securityMoney;
    }

    public BigDecimal getFundMoney() {
        return fundMoney;
    }

    public void setFundMoney(BigDecimal fundMoney) {
        this.fundMoney = fundMoney;
    }

    public BigDecimal getHouseMoney() {
        return houseMoney;
    }

    public void setHouseMoney(BigDecimal houseMoney) {
        this.houseMoney = houseMoney;
    }

    public BigDecimal getCarMoney() {
        return carMoney;
    }

    public void setCarMoney(BigDecimal carMoney) {
        this.carMoney = carMoney;
    }

    public BigDecimal getHouseMortgageBalance() {
        return houseMortgageBalance;
    }

    public void setHouseMortgageBalance(BigDecimal houseMortgageBalance) {
        this.houseMortgageBalance = houseMortgageBalance;
    }

    public BigDecimal getCarMortgageBalance() {
        return carMortgageBalance;
    }

    public void setCarMortgageBalance(BigDecimal carMortgageBalance) {
        this.carMortgageBalance = carMortgageBalance;
    }

    public BigDecimal getLoanBalance() {
        return loanBalance;
    }

    public void setLoanBalance(BigDecimal loanBalance) {
        this.loanBalance = loanBalance;
    }

    public SelfSupportCreditModelWeight getSelfSupportCreditModelWeight() {
        return selfSupportCreditModelWeight;
    }

    public void setSelfSupportCreditModelWeight(SelfSupportCreditModelWeight selfSupportCreditModelWeight) {
        this.selfSupportCreditModelWeight = selfSupportCreditModelWeight;
    }

    public BigDecimal getMonthControlMoney() {
        return monthControlMoney;
    }

    public void setMonthControlMoney(BigDecimal monthControlMoney) {
        this.monthControlMoney = monthControlMoney;
    }

    public Integer getLoanMonth() {
        return loanMonth;
    }

    public void setLoanMonth(Integer loanMonth) {
        this.loanMonth = loanMonth;
    }

    public Double getSum(){
        List<Method> methodStream = Arrays.stream(this.getClass().getMethods())
                .filter(method -> method.getName().matches("get(.*?)Score")).collect(Collectors.toList());
        return methodStream.stream().map(Try.of((Method method) -> (Double) method.invoke(this)))
                .reduce(0.0,Double::sum);
    }

    public BigDecimal getNetAsset(){
        return getBankMoney().add(getStockMoney().multiply(BigDecimal.valueOf(0.9))).add(getManageProductMoney())
                .add(getSecurityMoney()).add(getFundMoney()).add(getHouseMoney()).add(getCarMoney())
                .subtract(getHouseMortgageBalance()).subtract(getCarMortgageBalance())
                .subtract(getLoanBalance().subtract(getHouseMortgageBalance()).subtract(getCarMortgageBalance()));
    }

    public Double getNetAssetE(){
        double netAsset = getNetAsset().doubleValue();
        double netAssetCalculateValue = netAsset/10000;
        if (netAsset > 1000000){
            return 2.0;
        } else if(netAsset > 500000){
            return 0.3414 * Math.sqrt(netAssetCalculateValue) - 1.4142;
        } else if(netAsset >= 50000){
            return 0.1034 * Math.sqrt(netAssetCalculateValue) + 0.2688;
        } else {
            return 0.0;
        }
    }

    public BigDecimal getCreditLine(){
        return getMonthControlMoney()
                .multiply(BigDecimal.valueOf(getSum() * getNetAssetE() * getLoanMonth()));
    }

    public static void main(String[] args) {
        SelfSupportCreditModel selfSupportCreditModel = new SelfSupportCreditModel(new SelfSupportCreditModelWeightImpl());
        selfSupportCreditModel.setMonthControlMoney(new BigDecimal(20000));
        selfSupportCreditModel.setLoanMonth(11);
        selfSupportCreditModel.setBankMoney(new BigDecimal(50000));
        BigDecimal creditLine = selfSupportCreditModel.getCreditLine();
        System.out.println(creditLine);
    }

}